#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

# This script is a convenience wrapper around mockgen, designed to be
# added to PATH and used in go:generate commands.
#
# Usage:
#   //go:generate mockgen-wrapper [interfaces] [package]
#
# Two arguments => "reflect" mode for a different package.
#   Example: //go:generate mockgen-wrapper SecurityHubAPI github.com/aws/aws-sdk-go/service/securityhub/securityhubiface
#   Generates mocks for an interface specified e.g. in a third party package.
#   This is significantly slower than "source" mode, use only when necessary.
# One argument => "reflect" mode
#   Example: //go:generate mockgen-wrapper RepositoryFactory
#   Generates mocks for all interfaces specified (comma-delimited) in this package.
#   This is significantly slower than "source" mode, use only when necessary.
# Zero arguments => "source" mode
#   Example: //go:generate mockgen-wrapper
#   Generates mocks for all interfaces defined in the file that calls it.
#   This does not work with embedded interfaces.
#   This does not work when generating mocks for code that will be generated by
#     another go:generate command.

function die() {
	echo >&2 "$@"
	exit 1
}

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
[[ -n "${MOCKGEN_BIN:-}" ]] || MOCKGEN_BIN="$(make --quiet --no-print-directory -C "${PROJECT_ROOT}" which-mockgen)"
[[ -x "$MOCKGEN_BIN" ]] || die "mockgen binary not found or not executable at ${MOCKGEN_BIN}"

interfaces="${1:-}"
package="${2:-}"

if [[ -n "$interfaces" ]] && [[ -n "$package" ]]; then
  # Generate mocks for the specified interfaces in the specified package.
  out_file="mocks/${package}/mocks/mocks.go"
  out_file="${out_file#$(basename "$PWD")/}"  # Skip mocks/ prefix if current dir is called mocks/
  out_directory="$(dirname "${out_file}")"
  mkdir -p "${out_directory}"

  exec "$MOCKGEN_BIN" -package mocks -destination "${out_file}" "${package}" "${interfaces}"
elif [[ -n "$interfaces" ]]; then
  # Generate mocks for only the specified interfaces in the calling GOFILE.
  [[ -n "$GOFILE" ]] || die "Required environment variable GOFILE not set, must run using go:generate"
  package="$(go list)"
  [[ -n "$package" ]] || die "Could not determine Go package for working directory $PWD"
  out_file="mocks/${GOFILE}"
  out_directory="$(dirname "${out_file}")"
  mkdir -p "${out_directory}"

  exec "$MOCKGEN_BIN" -package mocks -destination "${out_file}" "${package}" "${interfaces}"
else
  # Generate mocks for all interfaces found in the calling GOFILE.
  [[ -n "$GOFILE" ]] || die "Required environment variable GOFILE not set, must run using go:generate"
  out_file="mocks/${GOFILE}"
  out_directory="$(dirname "${out_file}")"
  mkdir -p "${out_directory}"

  exec "$MOCKGEN_BIN" -package mocks -destination "${out_file}" -source "${GOFILE}"
fi
